#include "Lexer.h"
#include <cctype>
#include <iostream>

namespace MiniDB
{

    // 关键字映射定义
    const std::unordered_map<std::string, TokenType> Lexer::keywords_ = {
        {"SELECT", TokenType::SELECT},
        {"FROM", TokenType::FROM},
        {"WHERE", TokenType::WHERE},
        {"INSERT", TokenType::INSERT},
        {"INTO", TokenType::INTO},
        {"VALUES", TokenType::VALUES},
        {"UPDATE", TokenType::UPDATE},
        {"SET", TokenType::SET},
        {"DELETE", TokenType::DELETE},
        {"CREATE", TokenType::CREATE},
        {"TABLE", TokenType::TABLE},
        {"DROP", TokenType::DROP},
        {"ALTER", TokenType::ALTER},
        {"ADD", TokenType::ADD},
        {"COLUMN", TokenType::COLUMN},
        {"DATABASE", TokenType::DATABASE},
        {"USE", TokenType::USE},
        {"SHOW", TokenType::SHOW},
        {"TABLES", TokenType::TABLES},
        {"DESCRIBE", TokenType::DESCRIBE},
        {"BEGIN", TokenType::BEGIN},
        {"COMMIT", TokenType::COMMIT},
        {"ROLLBACK", TokenType::ROLLBACK},
        {"TRANSACTION", TokenType::TRANSACTION},
        {"PRIMARY", TokenType::PRIMARY},
        {"KEY", TokenType::KEY},
        {"NOT", TokenType::NOT},
        {"NULL", TokenType::NULL_TOKEN},
        {"INT", TokenType::INT},
        {"VARCHAR", TokenType::VARCHAR},
        {"FLOAT", TokenType::FLOAT},
        {"BOOLEAN", TokenType::BOOLEAN},
        {"DATE", TokenType::DATE},
        {"TEXT", TokenType::TEXT},
        {"AND", TokenType::AND},
        {"OR", TokenType::OR},
        {"LIKE", TokenType::LIKE},
        {"IN", TokenType::IN},
        {"BETWEEN", TokenType::BETWEEN},
        {"IS", TokenType::IS}};

    Lexer::Lexer(const std::string &sql)
        : sql_(sql), position_(0), line_(1), column_(1), current_char_('\0')
    {
        advance(); // 初始化第一个字符
    }

    void Lexer::advance()
    {
        if (position_ >= sql_.size())
        {
            current_char_ = '\0';
        }
        else
        {
            current_char_ = sql_[position_];
        }
        position_++;
        column_++;
    }

    char Lexer::peek() const
    {
        size_t peek_pos = position_;
        if (peek_pos >= sql_.size())
        {
            return '\0';
        }
        return sql_[peek_pos];
    }

    void Lexer::skipWhitespace()
    {
        while (current_char_ != '\0' && std::isspace(current_char_))
        {
            if (current_char_ == '\n')
            {
                line_++;
                column_ = 1;
            }
            advance();
        }
    }

    std::string Lexer::readIdentifier()
    {
        std::string result;

        // Read characters while they are alphanumeric or underscore
        while (current_char_ != '\0' &&
               (std::isalnum(current_char_) || current_char_ == '_'))
        {
            result += current_char_;
            advance();
        }

        return result;
    }

    std::string Lexer::readStringLiteral()
    {
        std::string result;
        char quote = current_char_;
        advance(); // 跳过开始的引号

        while (current_char_ != '\0' && current_char_ != quote)
        {
            if (current_char_ == '\\')
            {
                advance();
                if (current_char_ != '\0')
                {
                    if (current_char_ == 'n')
                        result += '\n';
                    else if (current_char_ == 't')
                        result += '\t';
                    else if (current_char_ == 'r')
                        result += '\r';
                    else if (current_char_ == '"')
                        result += '"';
                    else if (current_char_ == '\'')
                        result += '\'';
                    else if (current_char_ == '\\')
                        result += '\\';
                    else
                        result += current_char_;
                    advance();
                }
            }
            else
            {
                result += current_char_;
                advance();
            }
        }

        if (current_char_ == quote)
        {
            advance(); // 跳过结束的引号
        }

        return result;
    }

    std::string Lexer::readNumberLiteral()
    {
        std::string result;
        while (current_char_ != '\0' &&
               (std::isdigit(current_char_) || current_char_ == '.'))
        {
            result += current_char_;
            advance();
        }
        return result;
    }

    TokenType Lexer::getKeywordType(const std::string &word) const
    {
        auto it = keywords_.find(word);
        if (it != keywords_.end())
        {
            return it->second;
        }
        return TokenType::IDENTIFIER;
    }

    std::vector<Token> Lexer::tokenize()
    {
        tokens_.clear();

        while (current_char_ != '\0')
        {
            if (std::isspace(current_char_))
            {
                skipWhitespace();
                continue;
            }

            // 标识符或关键字
            if (std::isalpha(current_char_) || current_char_ == '_')
            {
                int start_column = column_;
                std::string identifier = readIdentifier();
                TokenType token_type = getKeywordType(identifier);
                tokens_.emplace_back(token_type, identifier, line_, start_column);
                continue;
            }

            // 字符串字面量
            if (current_char_ == '"' || current_char_ == '\'')
            {
                int start_column = column_;
                std::string string_value = readStringLiteral();
                tokens_.emplace_back(TokenType::STRING_LITERAL, string_value,
                                     line_, start_column);
                continue;
            }

            // 数字字面量
            if (std::isdigit(current_char_))
            {
                int start_column = column_;
                std::string number_value = readNumberLiteral();
                tokens_.emplace_back(TokenType::NUMBER_LITERAL, number_value,
                                     line_, start_column);
                continue;
            }

            // 操作符和分隔符
            int start_column = column_;
            if (current_char_ == '=')
            {
                tokens_.emplace_back(TokenType::EQUALS, "=", line_, start_column);
                advance();
            }
            else if (current_char_ == '!' && peek() == '=')
            {
                tokens_.emplace_back(TokenType::NOT_EQUALS, "!=", line_, start_column);
                advance();
                advance();
            }
            else if (current_char_ == '>' && peek() == '=')
            {
                tokens_.emplace_back(TokenType::GREATER_EQUALS, ">=", line_, start_column);
                advance();
                advance();
            }
            else if (current_char_ == '<' && peek() == '=')
            {
                tokens_.emplace_back(TokenType::LESS_EQUALS, "<=", line_, start_column);
                advance();
                advance();
            }
            else if (current_char_ == '>')
            {
                tokens_.emplace_back(TokenType::GREATER, ">", line_, start_column);
                advance();
            }
            else if (current_char_ == '<')
            {
                tokens_.emplace_back(TokenType::LESS, "<", line_, start_column);
                advance();
            }
            else if (current_char_ == ',')
            {
                tokens_.emplace_back(TokenType::COMMA, ",", line_, start_column);
                advance();
            }
            else if (current_char_ == ';')
            {
                tokens_.emplace_back(TokenType::SEMICOLON, ";", line_, start_column);
                advance();
            }
            else if (current_char_ == '(')
            {
                tokens_.emplace_back(TokenType::LPAREN, "(", line_, start_column);
                advance();
            }
            else if (current_char_ == ')')
            {
                tokens_.emplace_back(TokenType::RPAREN, ")", line_, start_column);
                advance();
            }
            else if (current_char_ == '.')
            {
                tokens_.emplace_back(TokenType::DOT, ".", line_, start_column);
                advance();
            }
            else if (current_char_ == '*')
            {
                tokens_.emplace_back(TokenType::STAR, "*", line_, start_column);
                advance();
            }
            else
            {
                // 未知字符，跳过
                std::cout << "Warning: Unknown character '" << current_char_
                          << "' at line " << line_ << ", column " << column_ << std::endl;
                advance();
            }
        }

        // 添加EOF标记
        tokens_.emplace_back(TokenType::EOF_TOKEN, "", line_, column_);
        return tokens_;
    }

} // namespace MiniDB
